home *** CD-ROM | disk | FTP | other *** search
- ### mindfa -- minimize a DFA
-
- record dfa(Q,S,d,q0,F) # a DFA
-
- procedure main()
-
- x := getdfa()
- every 1 to 10 do
- showdfa("Reduced",minimize(showdfa("Original",x)))
-
- end
-
- ## - getdfa() -- accept a dfa from input, return it
- ##
- procedure getdfa()
- local Q,S,d,q0,F
- local q,a
-
- Q := readset("Enter states (1 character names): ")
- S := readset("Enter input alphabet: ")
- F := readset("Enter Final states (subset of states): ")
- writes("What is the start state? ")
- q0 := read()
- d := table()
- every q := !Q & a := !S do {
- writes("enter delta(",q,",",a,") = ")
- d[q||":"||a] := read()
- }
- return dfa(Q,S,d,q0,F)
-
- end
-
-
- ## readset(s) - get a set
- #
- procedure readset(s)
- local t1
-
- writes(s)
- t1 := []
- every put(t1,!cset(read())) # the cset removes duplicates
- return t1
-
- end
-
- ## showdfa(msg,D) -- show a dfa
- #
- procedure showdfa(msg,D)
- local q,a
-
- every 1 to 3 do write()
- write(msg," Deterministic Finite Automaton is:")
- write()
- write("\t(Q,S,delta,q0,F)")
- write()
- write("where:")
- write()
- writeset("Q",D.Q)
- writeset("S",D.S)
- writeset("F",D.F)
- write("\tStart state is ",D.q0)
- write("\tDelta: ")
- every q := !D.Q do {
- every writes("\td(",q,",",a := !D.S,") = ",D.d[q||":"||a])
- write()
- }
- return D
-
- end
-
- ## writeset(msg,s) -- display a set
- #
- procedure writeset(msg,s)
- local tmp
- tmp := ""
- every tmp ||:= !s || ","
- write("\t",msg," = {",tmp[1:-1],"}")
- return
- end
-
- ## minimize(D) -- minimize a dfa
- #
- global distab, dlists
-
- procedure minimize(D)
- local F,QF
- local p,q,a,cs
-
- distab := table()
- dlists := table()
- F := D.F
- QF := diff(D.Q,D.F)
- every p := !F & q := !QF do
- distab[cset(p||q)] := "X"
- every ((p := !F & q := !F) |
- (p := !QF & q := !QF)) & p ~== q do
- if \distab[cset(D.d[p||":"||(a:=!D.S)]||D.d[q||":"||a])] then {
- distab[cset(p||q)] := "X"
- marklists(dlists[cset(p||q)])
- }
- else
- every a := !D.S do
- if D.d[p||":"||a] ~== D.d[q||":"||a] then {
- cs := cset(D.d[p||":"||a]||D.d[q||":"||a])
- if cs == cset(p||q) then next
- /dlists[cs] := []
- put(dlists[cs],cset(p||q))
- }
-
- return makemdfa(D,distab)
-
- end
-
- ## marklists(l) -- recursively mark the pair of nodes
- # on list l.
- procedure marklists(l)
- local e
-
- if /l then return
- every e := !l do {
- distab[e] := "X"
- marklists(dlists[e])
- }
- return
-
- end
-
- ## makemdfa(D,DT) -- Use the table from the minimization
- # to construct the minimal dfa
- procedure makemdfa(D,DT)
- local elist, etab, qset, tlist, echeck
- local p, q, Delta, q0
-
- etab := table() # table of new states
- qset := ''
- every p := !D.Q do {
- qset ++:= p
- plike := equiv(p,etab) | cset(p)
- every q := !diff(D.Q,qset) & p ~== q do
- if /distab[cset(p||q)] then {
- plike ++:= equiv(q,etab) | q
- }
- etab[plike] := plike
- }
- tlist := []
- elist := []
- Delta := table()
- q0 := equiv(D.q0,etab) # start state of reduced machine
- put(tlist,q0)
- put(elist,q0) # only worry about states reachable
- # from [q0]
- echeck := table() # keep track of states
- echeck[q0] := q0
- while q := get(tlist) do
- every a := !D.S do {
- Delta[q||":"||a] := equivdelta(q,a,D,etab)
- if /echeck[Delta[q||":"||a]] then {
- echeck[Delta[q||":"||a]] := Delta[q||":"||a]
- put(tlist,Delta[q||":"||a])
- put(elist,Delta[q||":"||a])
- }
- }
-
- return dfa(elist,D.S,Delta,q0,finalstates(D,elist))
- end
-
- ## equiv(q,el) -- return the equivalence class in el containing q
- #
- procedure equiv(q,el)
- every p := !el do
- if p++q == p then return p
- end
-
- ## equivdelta(p,a,D,el) -- apply delta to equiv. classes
- #
- procedure equivdelta(p,a,D,el)
- local q, r
- q := !p # any state in equiv. class p
- r := D.d[q||":"||a] # find state in original dfa
-
- return equiv(r,el) # return its equivalence class
- end
-
-
- ## finalstates(D,el) -- build the set of final states
- #
- procedure finalstates(D,el)
- local flist, p, q
-
- ftab := table()
- every p := !D.F do
- ftab[q := equiv(p,el)] := q
- flist := []
- every put(flist,(!sort(ftab))[1])
- return flist
- end
-
-
- ## diff(l1,l2) -- return the difference of two sets
- #
- procedure diff(l1,l2)
- local l,t1,t2
-
- t1 := ''
- every t1 ++:= !l1
-
- t2 := ''
- every t2 ++:= !l2
-
- l := []
- every put(l,!(t1--t2))
- if *l = 0 then fail
- return l
- end
-